package com.todo.delicacy.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.todo.common.common.entity.response.BizResponse;
import com.todo.common.common.entity.response.page.PageResult;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.content.api.request.*;
import com.todo.content.api.response.ContentDetailResponse;
import com.todo.content.api.response.ContentInfoResponse;
import com.todo.delicacy.application.convert.FoodConvert;
import com.todo.delicacy.application.entity.bo.FoodRecommendDetailBO;
import com.todo.delicacy.application.entity.condition.FoodRecommendDetailConditionBO;
import com.todo.delicacy.application.remote.ContentInfoRemote;
import com.todo.delicacy.application.service.ContentFoodRecommendService;
import com.todo.delicacy.infrastructure.entity.condition.ContentFoodRecommendCondition;
import com.todo.delicacy.infrastructure.entity.po.ContentFoodRecommendPO;
import com.todo.delicacy.infrastructure.repository.ContentFoodRecommendRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * (ContentFoodRecommend)表服务实现类
 *
 * @author zhangwenxiang
 * @since 2024-03-04 00:19:45
 */
@Slf4j
@Service("contentFoodRecommendService")
public class ContentFoodRecommendServiceImpl implements ContentFoodRecommendService {

    @Resource
    private ContentFoodRecommendRepository contentFoodRecommendRepository;
    @Resource
    private ContentInfoRemote contentInfoRemote;

    @Override
    @Transactional
    public Boolean insertFoodRecommendDetail(FoodRecommendDetailBO foodRecommendDetailBO) {
        if (foodRecommendDetailBO == null || foodRecommendDetailBO.getFoodRecommendBO() == null || foodRecommendDetailBO.getFoodContentBO() == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }

        SavePreCheckRequest request = FoodConvert.buildToSavePreCheckRequest(foodRecommendDetailBO, true);
        BizResponse<Boolean> preCheck = contentInfoRemote.savePreCheck(request);
        if (preCheck == null || !preCheck.isSuccess() || !preCheck.getData()) {
            log.warn("ContentFoodRecommendService#insertFoodRecommendDetail 新增食品推荐内容详情失败，保存内容信息前置校验失败 foodRecommendDetailBO：【{}】", JSONObject.toJSONString(foodRecommendDetailBO));
            return false;
        }
        InsertContentDetailRequest saveRequest = FoodConvert.buildToInsertContentDetailRequest(foodRecommendDetailBO);
        BizResponse<Long> contentResult = contentInfoRemote.insertContentDetail(saveRequest);
        if (contentResult == null || !contentResult.isSuccess() || contentResult.getData() == null) {
            log.warn("ContentFoodRecommendService#insertFoodRecommendDetail 新增食品推荐内容详情失败，内容保存失败 foodRecommendDetailBO：【{}】", JSONObject.toJSONString(foodRecommendDetailBO));
            return false;
        }
        Long contentId = contentResult.getData();
        foodRecommendDetailBO.getFoodRecommendBO().setContentId(contentId);
        ContentFoodRecommendPO foodRecommendPO = FoodConvert.convertToContentFoodRecommendPO(foodRecommendDetailBO);
        foodRecommendPO.setContentId(contentId);
        Boolean saveResult = contentFoodRecommendRepository.insertFoodContentRecommend(foodRecommendPO);
        if (!saveResult) {
            log.error("ContentFoodRecommendService#insertFoodRecommendDetail 新增食品推荐内容详情失败，推荐信息保存失败 foodRecommendPO：【{}】", JSONObject.toJSONString(foodRecommendPO));
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED);
        }
        return saveResult;
    }

    @Override
    @Transactional
    public Boolean updateFoodRecommendDetail(FoodRecommendDetailBO foodRecommendDetailBO) {
        if (foodRecommendDetailBO == null || foodRecommendDetailBO.getFoodRecommendBO() == null || foodRecommendDetailBO.getFoodRecommendBO().getId() == null || foodRecommendDetailBO.getFoodContentBO() == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        FoodRecommendDetailBO alreadyFoodRecommendDetailBO = queryFoodRecommendDetailById(foodRecommendDetailBO.getFoodRecommendBO().getId());
        if (alreadyFoodRecommendDetailBO == null) {
            throw new BizException(BizErrorCodeEnum.DATA_NOT_EXIST);
        }
        SavePreCheckRequest request = FoodConvert.buildToSavePreCheckRequest(foodRecommendDetailBO, true);
        BizResponse<Boolean> preCheck = contentInfoRemote.savePreCheck(request);
        if (preCheck == null || !preCheck.isSuccess() || !preCheck.getData()) {
            log.warn("ContentFoodRecommendService#updateFoodRecommendDetail 更新食品推荐内容详情失败，保存内容信息前置校验失败 foodRecommendDetailBO：【{}】", JSONObject.toJSONString(foodRecommendDetailBO));
            return false;
        }
        UpdateContentDetailRequest saveRequest = FoodConvert.buildToUpdateContentDetailRequest(foodRecommendDetailBO);
        BizResponse<Boolean> contentResult = contentInfoRemote.updateContentDetail(saveRequest);
        if (contentResult == null || !contentResult.isSuccess() || !contentResult.getData()) {
            log.error("ContentFoodRecommendService#updateFoodRecommendDetail 更新食品推荐内容详情失败，内容更新失败 foodRecommendDetailBO：【{}】", JSONObject.toJSONString(foodRecommendDetailBO));
            return false;
        }
        ContentFoodRecommendPO foodRecommendPO = FoodConvert.convertToContentFoodRecommendPO(foodRecommendDetailBO);
        Boolean updateResult = contentFoodRecommendRepository.updateFoodContentRecommend(foodRecommendPO);
        if (!updateResult) {
            log.error("ContentFoodRecommendService#updateFoodRecommendDetail 更新食品推荐内容详情失败，推荐信息更新失败 foodRecommendPO：【{}】", JSONObject.toJSONString(foodRecommendPO));
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED);
        }
        return updateResult;
    }

    @Override
    public Boolean removeFoodRecommendDetailById(Long id) {
        if (id == null || id < 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        ContentFoodRecommendPO contentFoodRecommendPO = contentFoodRecommendRepository.queryContentFoodRecommendPOById(id);
        if (contentFoodRecommendPO == null) {
            log.info("ContentFoodRecommendService#removeFoodRecommendDetailById 删除没事推荐内容完成，根据主键id查询数据为空，默认删除成功 id:【{}】", id);
            return true;
        }
        RemoveContentDetailByIdRequest request = new RemoveContentDetailByIdRequest();
        request.setContentId(id);
        BizResponse<Boolean> contentResult = contentInfoRemote.removeContentDetailById(request);
        if (contentResult == null || !contentResult.isSuccess() || !contentResult.getData()) {
            log.error("ContentFoodRecommendService#removeFoodRecommendDetailById 删除美食推荐内容详情失败，内容删除失败 id:【{}】", id);
            return false;
        }
        Boolean removeResult = contentFoodRecommendRepository.removeContentFoodRecommendPOById(id);
        if (!removeResult) {
            log.error("ContentFoodRecommendService#removeFoodRecommendDetailById 删除美食推荐内容详情失败，推荐信息删除失败 id:【{}】", id);
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED);
        }

        return removeResult;
    }

    @Override
    @Transactional
    public Boolean removeFoodRecommendDetailByContentId(Long contentId) {
        if (contentId == null || contentId < 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        ContentFoodRecommendPO contentFoodRecommendPO = contentFoodRecommendRepository.queryContentFoodRecommendPOByContentId(contentId);
        if (contentFoodRecommendPO == null) {
            log.info("ContentFoodRecommendService#removeFoodRecommendDetailByContentId 删除美食推荐内容详情失败，根据内容id查询数据为空，默认删除成功 contentId:【{}】", contentId);
            return true;
        }
        RemoveContentDetailByIdRequest request = new RemoveContentDetailByIdRequest();
        request.setContentId(contentId);
        BizResponse<Boolean> contentResult = contentInfoRemote.removeContentDetailById(request);
        if (contentResult == null || !contentResult.isSuccess() || !contentResult.getData()) {
            log.error("ContentFoodRecommendService#removeFoodRecommendDetailByContentId 删除美食推荐内容详情失败，内容删除失败 contentId:【{}】", contentId);
            return false;
        }
        Boolean removeResult = contentFoodRecommendRepository.removeContentFoodRecommendPOById(contentFoodRecommendPO.getId());
        if (!removeResult) {
            log.error("ContentFoodRecommendService#removeFoodRecommendDetailByContentId 删除美食推荐内容详情失败，推荐信息删除失败 contentId:【{}】", contentId);
            return false;
        }
        return true;
    }

    @Override
    public FoodRecommendDetailBO queryFoodRecommendDetailById(Long id) {
        if (id == null || id < 0) {
            return null;
        }
        ContentFoodRecommendPO contentFoodRecommendPO = contentFoodRecommendRepository.queryContentFoodRecommendPOById(id);
        if (contentFoodRecommendPO == null) {
            return null;
        }
        QueryContentDetailByIdRequest request = new QueryContentDetailByIdRequest();
        request.setContentId(contentFoodRecommendPO.getContentId());
        BizResponse<ContentDetailResponse> bizResponse = contentInfoRemote.queryContentDetailById(request);
        if (bizResponse == null || !bizResponse.isSuccess() || bizResponse.getData() == null) {
            return null;
        }
        return FoodConvert.buildFoodRecommendDetailBO(bizResponse.getData(), contentFoodRecommendPO);
    }

    @Override
    public FoodRecommendDetailBO queryFoodRecommendDetailByContentId(Long contentId) {
        if (contentId == null || contentId < 0) {
            return null;
        }
        ContentFoodRecommendPO contentFoodRecommendPO = contentFoodRecommendRepository.queryContentFoodRecommendPOByContentId(contentId);
        if (contentFoodRecommendPO == null) {
            return null;
        }
        QueryContentDetailByIdRequest request = new QueryContentDetailByIdRequest();
        request.setContentId(contentId);
        BizResponse<ContentDetailResponse> bizResponse = contentInfoRemote.queryContentDetailById(request);
        if (bizResponse == null || !bizResponse.isSuccess() || bizResponse.getData() == null) {
            return null;
        }
        return FoodConvert.buildFoodRecommendDetailBO(bizResponse.getData(), contentFoodRecommendPO);
    }

    @Override
    public PageResult<FoodRecommendDetailBO> queryFoodRecommendDetailByCondition(FoodRecommendDetailConditionBO conditionBO) {
        if (conditionBO == null) {
            return new PageResult<>();
        }
        ContentFoodRecommendCondition condition = FoodConvert.convertToContentFoodRecommendCondition(conditionBO);
        PageResult<ContentFoodRecommendPO> pageResult = contentFoodRecommendRepository.queryContentFoodRecommendByCondition(condition);
        if (pageResult == null) {
            return new PageResult<>();
        }
        PageResult<FoodRecommendDetailBO> result = new PageResult<>();
        result.setPageSize(pageResult.getPageSize());
        result.setTotal(pageResult.getTotal());
        result.setCurrentIndex(pageResult.getCurrentIndex());
        result.setPageNum(pageResult.getPageNum());
        result.setHasNext(pageResult.isHasNext());

        if (CollectionUtils.isEmpty(pageResult.getResults())) {
            return result;
        }
        List<Long> contentIdList = pageResult.getResults().stream().map(ContentFoodRecommendPO::getContentId).collect(Collectors.toList());
        QueryContentInfoByIdListRequest request = new QueryContentInfoByIdListRequest();
        request.setContentIdList(contentIdList);
        BizResponse<List<ContentInfoResponse>> bizResponse = contentInfoRemote.queryContentInfoByIdList(request);
        if (bizResponse == null || !bizResponse.isSuccess() || bizResponse.getData() == null) {
            return result;
        }
        Map<Long, ContentInfoResponse> contentInfoBOMap = bizResponse.getData().stream().collect(Collectors.toMap(ContentInfoResponse::getContentId, Function.identity()));
        List<FoodRecommendDetailBO> partnerContentDetailBOList = new ArrayList<>();
        for (ContentFoodRecommendPO contentFoodRecommendPO : pageResult.getResults()) {
            ContentInfoResponse contentInfoResponse = contentInfoBOMap.get(contentFoodRecommendPO.getContentId());
            if (contentInfoResponse == null) {
                continue;
            }
            FoodRecommendDetailBO partnerContentDetailBO = FoodConvert.buildFoodRecommendDetailBO(contentInfoResponse, contentFoodRecommendPO);
            partnerContentDetailBOList.add(partnerContentDetailBO);
        }
        result.setResults(partnerContentDetailBOList);
        return result;
    }
}
